﻿using System;
using System.Net;
using System.ServiceModel;
using System.ServiceModel.Channels;
using Bricks;
using Bricks.Caching;

namespace Motar.ServiceModel
{

    /// <summary>
    /// 
    /// </summary>
    public class CookieMessageInspector : FacadeBase<ICacheFacade>, ICookieMessageInspector
    {

        /// <summary>
        /// 
        /// </summary>
        protected static readonly string StorageKey = Guid.NewGuid().ToString();

        /// <summary>
        /// 
        /// </summary>
        /// <param name="cacheFacade"></param>
        public CookieMessageInspector(ICacheFacade cacheFacade) :
            base(() => cacheFacade)
        {
            if (cacheFacade == null)
            {
                throw new ArgumentNullException("cacheFacade");
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="reply"></param>
        /// <param name="correlationState"></param>
        public void AfterReceiveReply(ref Message reply, object correlationState)
        {
            HttpResponseMessageProperty httpResponseMessage;

            httpResponseMessage = reply.Properties[HttpResponseMessageProperty.Name] as HttpResponseMessageProperty;

            if (httpResponseMessage != null)
            {
                string cookie = httpResponseMessage.Headers[HttpResponseHeader.SetCookie];

                if (!string.IsNullOrWhiteSpace(cookie))
                {
                    Execute(cacheFacade =>
                    {
                        if (cacheFacade.Contains(StorageKey))
                        {
                            cacheFacade.Remove(StorageKey);
                        }

                        cacheFacade.Add(StorageKey, cookie);
                    });
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="request"></param>
        /// <param name="channel"></param>
        /// <returns></returns>
        public object BeforeSendRequest(ref Message request, IClientChannel channel)
        {
            string cookie = Execute<string>(contextFacade => contextFacade.Contains(StorageKey) ? contextFacade.Get(StorageKey) as string : null);

            if (!string.IsNullOrWhiteSpace(cookie))
            {
                HttpRequestMessageProperty httpRequestMessage;

                if (request.Properties.ContainsKey(HttpRequestMessageProperty.Name))
                {
                    httpRequestMessage = request.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;

                    if (httpRequestMessage == null)
                    {
                        httpRequestMessage = new HttpRequestMessageProperty();

                        request.Properties[HttpRequestMessageProperty.Name] = httpRequestMessage;
                    }
                }
                else
                {
                    httpRequestMessage = new HttpRequestMessageProperty();

                    request.Properties[HttpRequestMessageProperty.Name] = httpRequestMessage;
                }

                httpRequestMessage.Headers[HttpRequestHeader.Cookie] = cookie;
            }

            return null;
        }
    }
}
